package com.java.mall_imooc.common.exception;

import cn.hutool.core.exceptions.ExceptionUtil;
import com.java.mall_imooc.common.enums.ResultEnum;
import com.java.mall_imooc.common.utils.R;
import io.jsonwebtoken.ExpiredJwtException;
import lombok.extern.slf4j.Slf4j;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.jdbc.BadSqlGrammarException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.naming.SizeLimitExceededException;

/**
 * 全局异常处理器
 * @author jiangli
 * @since 2020-03-15 21:57
 */
@RestControllerAdvice
@Slf4j
public class RRExceptionHandler {
    private Logger logger = LoggerFactory.getLogger(getClass());

    /**
     * 处理自定义异常
     */
    @ExceptionHandler(RRException.class)
    public R handleRRException(RRException e) {
        // 使用日志记录详细错误信息
        log.error(ExceptionUtil.getMessage(e));

        return R.error(e.getMessage());
    }

    /**
     * 参数校验Exception
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public Object validExceptionHandler(MethodArgumentNotValidException e){
        FieldError fieldError = e.getBindingResult().getFieldError();
        assert fieldError != null;
        log.error(fieldError.getField() + ":" + fieldError.getDefaultMessage());
        // 将错误的参数的详细信息封装到统一的返回实体
        return R.error(fieldError.getDefaultMessage());
    }

    /**
     * 参数校验Exception
     */
    @ExceptionHandler(BindException.class)
    public Object validExceptionHandler(BindException e){
        FieldError fieldError = e.getBindingResult().getFieldError();
        assert fieldError != null;
        log.error(fieldError.getField() + ":" + fieldError.getDefaultMessage());
        return R.error(fieldError.getDefaultMessage());
    }

    /**
     * Sql语法错误
     */
    @ExceptionHandler(BadSqlGrammarException.class)
    public R error(BadSqlGrammarException e){
        log.error(e.getMessage());
        return R.error(ResultEnum.BAD_SQL_GRAMMAR);
    }

    /**
     * json解析异常
     */
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public R error(HttpMessageNotReadableException e){
        log.error(e.getMessage());
        return R.error(ResultEnum.JSON_PARSE_ERROR);
    }

    /**
     * 文件上传错误
     */
    @ExceptionHandler(SizeLimitExceededException.class)
    public R error(SizeLimitExceededException e){
        log.error(e.getMessage());
        return R.error(ResultEnum.FILE_UPLOAD_ERROR);
    }

    /**
     * jwt解析错误
     */
    @ExceptionHandler(ExpiredJwtException.class)
    public R error(ExpiredJwtException e){
        log.error(e.getMessage());
        return R.error(ResultEnum.RE_LOGIN);
    }

    @ExceptionHandler(DuplicateKeyException.class)
    public R handleDuplicateKeyException(DuplicateKeyException e) {
        logger.error(e.getMessage(), e);

        return R.error(HttpStatus.BAD_REQUEST.value(), "数据库中已存在该记录");
    }

/*	@ExceptionHandler(AuthorizationException.class)
	public R handleAuthorizationException(AuthorizationException e){
		logger.error(e.getMessage(), e);
		return R.error("没有权限，请联系管理员授权");
	}

	@ExceptionHandler(NoHandlerFoundException.class)
	public R handlerNoFoundException(Exception e) {
		logger.error(e.getMessage(), e);
		return R.error(404, "路径不存在，请检查路径是否正确");
	}*/

    @ExceptionHandler(Exception.class)
    public R handleException(Exception e) {
        logger.error(e.getMessage(), e);

		return R.error(HttpStatus.BAD_REQUEST.value(), e.getMessage());
    }
}
